home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / bipl.zip / PROGS.ZIP / GRPSORT.ICN < prev    next >
Text File  |  1992-09-28  |  6KB  |  187 lines

  1. ############################################################################
  2. #
  3. #    File:     grpsort.icn
  4. #
  5. #    Subject:  Program to sort groups of lines
  6. #
  7. #    Author:   Thomas R. Hicks
  8. #
  9. #    Date:     June 10, 1988
  10. #
  11. ###########################################################################
  12. #  
  13. #     This program sorts input containing ``records'' defined to be
  14. #  groups of consecutive lines. Output is written to standard out-
  15. #  put.  Each input record is separated by one or more repetitions
  16. #  of a demarcation line (a line beginning with the separator
  17. #  string).  The first line of each record is used as the key.
  18. #  
  19. #     If no separator string is specified on the command line, the
  20. #  default is the empty string. Because all input lines are trimmed
  21. #  of whitespace (blanks and tabs), empty lines are default demarca-
  22. #  tion lines. The separator string specified can be an initial sub-
  23. #  string of the string used to demarcate lines, in which case the
  24. #  resulting partition of the input file may be different from a
  25. #  partition created using the entire demarcation string.
  26. #  
  27. #     The -o option sorts the input file but does not produce the
  28. #  sorted records.  Instead it lists the keys (in sorted order) and
  29. #  line numbers defining the extent of the record associated with
  30. #  each key.
  31. #  
  32. #     The use of grpsort is illustrated by the following examples.
  33. #  The command
  34. #  
  35. #          grpsort "catscats" <x >y
  36. #  
  37. #  sorts the file x, whose records are separated by lines containing
  38. #  the string "catscats", into the file y placing a single line of
  39. #  "catscats" between each output record. Similarly, the command
  40. #  
  41. #          grpsort "cats" <x >y
  42. #  
  43. #  sorts the file x as before but assumes that any line beginning
  44. #  with the string "cats" delimits a new record. This may or may not
  45. #  divide the lines of the input file into a number of records dif-
  46. #  ferent from the previous example.  In any case, the output
  47. #  records will be separated by a single line of "cats".  Another
  48. #  example is
  49. #  
  50. #          grpsort -o <bibliography >bibkeys
  51. #  
  52. #  which sorts the file bibliography and produces a sorted list of
  53. #  the keys and the extents of the associated records in bibkeys.
  54. #  Each output key line is of the form:
  55. #  
  56. #          [s-e] key
  57. #  
  58. #  where
  59. #  
  60. #          s     is the line number of the key line
  61. #          e     is the line number of the last line
  62. #          key   is the actual key of the record
  63. #  
  64. #  
  65. ############################################################################
  66. #
  67. #  Links: usage
  68. #
  69. ############################################################################
  70.  
  71. link usage
  72.  
  73. global lcount, linelst, ordflag
  74.  
  75. procedure main(args)
  76.    local division, keytable, keylist, line, info, nexthdr, null
  77.    linelst := []
  78.    keytable := table()
  79.    lcount := 0
  80.  
  81.    if *args = 2 then
  82.       if args[1] == "-o" then
  83.           ordflag := pop(args)
  84.       else
  85.           Usage("groupsort [-o] [separator string] <file >sortedfile")
  86.  
  87.    if *args = 1 then {
  88.       if args[1] == "?" then
  89.           Usage("groupsort [-o] [separator string] <file >sortedfile")
  90.       if args[1] == "-o" then
  91.           ordflag := pop(args)
  92.       else
  93.           division := args[1]
  94.       }
  95.  
  96.    if *args = 0 then
  97.       division := ""
  98.  
  99.    nexthdr := lmany(division) | fail    # find at least one record or quit
  100.    info := [nexthdr,[lcount]]
  101.  
  102.    # gather all data lines for this group/record
  103.    while line := getline() do {
  104.       if eorec(division,line) then {    # at end of this record
  105.           # enter record info into sort key table
  106.           put(info[2],lcount-1)
  107.           enter(info,keytable)
  108.           # look for header of next record
  109.           if nexthdr := lmany(division) then
  110.           info := [nexthdr,[lcount]] # begin next group/record
  111.           else
  112.           info := null
  113.           }
  114.       }
  115.    # enter last line info into sort key table
  116.    if \info then {
  117.       put(info[2],lcount)
  118.       enter(info,keytable)
  119.       }
  120.  
  121.    keylist := sort(keytable,1)        # sort by record headers
  122.    if \ordflag then
  123.       printord(keylist)        # list sorted order of records
  124.    else
  125.       printrecs(keylist,division)    # print records in order
  126. end
  127.  
  128. # enter - enter the group info into the sort key table
  129. procedure enter(info,tbl)
  130.    if /tbl[info[1]] then        # new key value
  131.       tbl[info[1]] := [info[2]]
  132.    else
  133.       put(tbl[info[1]],info[2])    # add occurrance info
  134. end
  135.  
  136. # eorec - suceed if a delimiter string has been found, fail otherwise
  137. procedure eorec(div,str)
  138.    if div == "" then            # If delimiter string is empty,
  139.       if str == div then return    # then make exact match
  140.       else
  141.           fail
  142.    if match(div,str) then return    # Otherwise match initial string.
  143.    else
  144.       fail
  145. end
  146.  
  147. # getline - get the next line (or fail), trim off trailing tabs and blanks.
  148. procedure getline()
  149.    local line
  150.    static trimset
  151.    initial trimset := ' \t'
  152.    if line := trim(read(),trimset) then {
  153.       if /ordflag then    # save only if going to print later
  154.           put(linelst,line)
  155.       lcount +:= 1
  156.       return line
  157.       }
  158. end
  159.  
  160. # lmany - skip over many lines matching string div.
  161. procedure lmany(div)
  162.    local line
  163.    while line := getline() do {
  164.       if eorec(div,line) then next    #skip over multiple dividing lines
  165.       return line
  166.       }
  167. end
  168.  
  169. # printord - print only the selection order of the records.
  170. procedure printord(slist)
  171.    local x, y
  172.    every x := !slist do
  173.       every y := !x[2] do
  174.           write(y[1],"-",y[2],"\t",x[1])
  175. end
  176.  
  177. # printrecs - write the records in sorted order, separated by div string.
  178. procedure printrecs(slist,div)
  179.    local x, y, z
  180.    every x := !slist do 
  181.       every y := !x[2] do {
  182.           every z := y[1] to y[2] do
  183.           write(linelst[z])
  184.           write(div)
  185.           }
  186. end
  187.